/******************************************************************************
 * SVN­Versioning-Information:
 * ­­­­­­­­­­­­­­­­­­­­­­­­---------------------
 * $LastChangedRevision: 6 $
 * $LastChangedBy: c.a.duevel $
 * $LastChangedDate: 2009-08-26 15:12:37 +0000 (Wed, 26 Aug 2009) $
 * $HeadURL: http://robofight.googlecode.com/svn/trunk/Server/src/de/hft_stuttgart/botwar/server/model/Ranking.java $
 ******************************************************************************/
package de.hft_stuttgart.botwar.server.model;

import de.hft_stuttgart.botwar.server.DataBase;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Vector;

/**
 * @author pmv-mail@gmx.de
 */
public final class Ranking implements Comparable {
    private static List<Ranking> list = new Vector<Ranking>();
    private String playerID;
    private long coins;

    private Ranking(){
    }

    private Ranking(final String playerID){
        this.playerID = playerID;
    }

    private Ranking(final String playerID, final long coins){
       this.playerID = playerID;
       this.coins = coins;
       list.add(this);
       Collections.sort(list);
    }

    /**
     * Called on serverstart. Initializes the rankingsystem and load all
     * players.
     */
    public static void init(){
        list.clear();
        Map<String, Long> coinList = DataBase.get().getPlayerCoins();
        for (String player : coinList.keySet()) {
            new Ranking(player, coinList.get(player));
        }
    }

    /**
     * Called from login class if a new player has been registered.
     * @param playerID id from player to be added
     * @return new rankingobject from the player
     */
    public static Ranking add(final String playerID){
        return new Ranking(playerID, 0);
    }

    /**
     * Called to get the instance for a player.
     * @param playerID id from the player
     * @return Ranking-Object
     */
    public static Ranking get(final String playerID){
        return list.get(list.indexOf(new Ranking(playerID)));
    }

    /**
     * If a player will be removed from system, this must be called additional
     */
    public void remove(){
        list.remove(this);
    }

    /**
     * Returns the coins from the rank
     * @return coins
     */
    public long getCoins() {
        return coins;
    }

    /**
     * If a player get more coins, the Ranking must be updated
     * @param coins additional amount of coins the player has get
     */
    public void addCoins(final long coins){
        if (coins < 0){
            throw new
                IllegalArgumentException("Substraction of coins not allowed!");
        }
        this.coins += coins;
        Collections.sort(list);
    }

    /**
     * Returns the playerID from the rank
     * @return playerID
     */
    public String getPlayerID() {
        return playerID;
    }

    /**
     * Returns the rank
     * @return rank
     */
    public int getRank() {
        return list.indexOf(this) + 1;
    }


    /**
     * Returns the given page of rankings with the given size
     * @param size number of rows per page
     * @param page the wanted page-index, beginning by one
     * @return list of Ranking-Objects
     */
    public static List<Ranking> getPage(final int size, final int page) {
        if (size <= 0 || page <= 0) {
            throw new IllegalArgumentException("size and page must be positiv");
        }

        int index = size * (page - 1);
        int length = size;
        if (index > list.size() - 1){
            return null;
        } else if (index + length > list.size() - 1){
            length = list.size() - index;
        }
        return list.subList(index, index + length);
    }


    /**
     *
     * @param obj object to be compared
     * @return true if the object is equal to this object, otherwise false
     */
    @Override
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (!(obj instanceof Ranking)) {
            return false;
        }
        Ranking ranking = (Ranking) obj;
        if(this.getPlayerID().equals(ranking.getPlayerID())) {
            return true;
        }
        return false;
    }

    /**
     *
     * @return hascode from this object
     */
    @Override
    public int hashCode() {
        int hash = 5;
        hash = 53 * hash +
                        (this.playerID != null ? this.playerID.hashCode() : 0);
        return hash;
    }

    /**
     *
     * @param o object to be compared
     * @return if this object has a higher rank, it will return a negativ
     * number, if it has a lower rank, it will return a positiv number,
     * otherwise zero.
     */
    public int compareTo(final Object o) {
        Ranking r = (Ranking) o;
        return ((int) (r.getCoins() - this.getCoins()));
    }
}
